#include "os.h"

/* 在 entry.S 中定义 */
extern void switch_to(struct context *next);

#define MAX_TASKS 10
#define STACK_SIZE 1024
/*
 * 在标准 RISC-V 调用约定中，栈指针 sp
 * 始终保持 16 字节对齐。
 */
uint8_t __attribute__((aligned(16))) task_stack[MAX_TASKS][STACK_SIZE];
struct context ctx_tasks[MAX_TASKS];

/*
 * _top 用于标记 ctx_tasks 中当前可用的最大位置；表示创建了多少个任务。
 * _current 用于指向当前正在运行任务的上下文。
 */
static int _top = 0;
static int _current = -1;

static void w_mscratch(reg_t x)
{
	asm volatile("csrw mscratch, %0" : : "r" (x));
}

void sched_init()
{
	w_mscratch(0);
}

/*
 * 实现一个简单的循环 FIFO 调度器
 * 初始：_top = 2, _current = -1
 */
void schedule()
{
	if (_top <= 0) 
	{
		panic("Num of task should be greater than zero!");
		return;
	}

	_current = (_current + 1) % _top;
	struct context *next = &(ctx_tasks[_current]);
	switch_to(next);
}

/*
 * 说明（DESCRIPTION）
 * 	创建一个任务。
 * 	- start_routin：任务入口函数
 * 返回值（RETURN VALUE）
 * 	0：成功
 * 	-1：发生错误时返回
 */
int task_create(void (*start_routin)(void))
{
	if (_top < MAX_TASKS) 
	{
		ctx_tasks[_top].sp = (reg_t) &task_stack[_top][STACK_SIZE];
		ctx_tasks[_top].ra = (reg_t) start_routin;
		_top++;
		return 0;
	} else 
	{
		return -1;
	}
}

/*
 * 说明（DESCRIPTION）
 * 	task_yield() 使调用该函数的任务让出 CPU，
 * 	从而由下一个任务获得运行机会。
 */
void task_yield()
{
	schedule();
}

/*
 * 一个非常粗糙的实现，仅用于消耗 CPU
 */
void task_delay(volatile int count)
{
	count *= 50000;
	while (count--);
}

